package com.znxs.bs_c.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.znxs.bs_c.common.Result;
import com.znxs.bs_c.common.Status;
import com.znxs.bs_c.entity.UserFile;
import com.znxs.bs_c.service.impl.FileServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;

/**
 * 文件上传相关接口
 */
@RestController
@RequestMapping("/file")
public class FileController {

    @Value("${files.upload.path}")
    private String fileUploadPath;

    @Autowired
    private FileServiceImpl fileService;

    // 获取图片url
    @GetMapping("/imgName")
    public Result getImgUrlByImgName (@RequestParam("imgName") String imgName){
        QueryWrapper<UserFile> userFileQueryWrapper = new QueryWrapper<>();
        userFileQueryWrapper.eq("name",imgName);
        List<UserFile> list = fileService.list(userFileQueryWrapper);
        return Result.success(list.get(0));
    }


    // 查询所有文件
    @GetMapping("/page")
    public Result getFilePage(@RequestParam("current") Integer current,
                              @RequestParam("pageSize") Integer pageSize,
                              @RequestParam("name") String name,
                              @RequestParam("size") String size,
                              @RequestParam("type") String type
                              ){
        IPage<UserFile> userFilePage = new Page<>(current, pageSize);
        QueryWrapper<UserFile> userFileQueryWrapper = new QueryWrapper<>();
        userFileQueryWrapper.like("name",name).like("size",size).like("type",type);
        userFileQueryWrapper.orderByDesc("id"); // 逆序排列
        IPage<UserFile> page = fileService.page(userFilePage, userFileQueryWrapper);
        return Result.success(page);
    }

    /**
     * 更新状态 是否删除 是否禁用
     * @param userFile
     * @return
     */
    @PutMapping()
    public Result updateFileStatus(@RequestBody UserFile userFile) {
        return Result.success(fileService.updateById(userFile));
    }

    @DeleteMapping("/{id}")
    public Result deleteFiles(@PathVariable("id") Integer id){
        return Result.success(fileService.removeById(id));
    }

    @DeleteMapping()
    public Result deleteFiles(@RequestBody List<Integer> ids){
        UpdateWrapper<UserFile> userFileUpdateWrapper = new UpdateWrapper<>();
        boolean flag = false;
        for (Integer id :ids) {
            userFileUpdateWrapper.eq("id",id).set("is_delete",true);
            flag = fileService.update(userFileUpdateWrapper);
        }
        return flag ? Result.success():Result.error(Status.SystemError.getCode(),"数据错误");
    }


    /**
     * 文件上传接口
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping("/upload")
    public String upload(@RequestParam MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename();
        String type = FileUtil.extName(originalFilename);
        long size = file.getSize();

        // 判断配置的文件目录是否存在，若不存在，则创建一个新的文件目录
        if (!new File(fileUploadPath).exists()) {
            new File(fileUploadPath).mkdir();
        }
        // 定义一个唯一的文件标识码
        String uuid = IdUtil.fastSimpleUUID();
        String fileName = uuid + StrUtil.DOT + type;  // 文件后缀
        File uploadPath = new File(fileUploadPath + fileName); // 文件名+uuid 就算是同一个文件同一个名字也会使用不同的uuid

        // 先上传文件到磁盘 查看有没有相同的md5 有就删掉上传的文件
        file.transferTo(uploadPath);
        // 获取文件的md5
        String md5 = SecureUtil.md5(uploadPath);
        // 查询md5对应的文件是否存在
        UserFile DBFile = getFileByMd5(md5);
        String url;
        if (DBFile != null) {
            // 若存在，就直接获取原数据库文件的url 然后删掉上传的文件
            url = DBFile.getUrl();
            uploadPath.delete();
        } else {
            // 不存在，就赋值给url
            url = "http://localhost:8888/file/file_name/" + originalFilename+"/file_url/"+fileName;
        }

        // 存取到数据库
        UserFile userFile = new UserFile();
        userFile.setName(originalFilename);
        userFile.setType(type);
        userFile.setSize(size / 1024);
        userFile.setMd5(md5);
        userFile.setUrl(url);
        fileService.save(userFile);
        return url;
    }

    /**
     * 文件下载接口
     * http://localhost:8888/file/file_url/{fileName}
     *
     * @param fileName
     * @param response
     * @throws IOException
     */
    @GetMapping("/file_name/{fileName}/file_url/{fileUrl}")
    public void download(@PathVariable("fileName") String fileName,@PathVariable("fileUrl") String fileUrl, HttpServletResponse response) throws IOException {
        System.out.println(fileName);  // 中文
        System.out.println(new String(fileName.getBytes("UTF-8"),"iso-8859-1"));
        // 根据文件的唯一标识获取文件
        File uploadFile = new File(fileUploadPath + fileUrl);
        // 流的方式下载
        ServletOutputStream os = response.getOutputStream();
        response.setContentType("multipart/form-data");
        response.addHeader("Content-Disposition","attachment;fileName=" +new String(fileName.getBytes("UTF-8"),"iso-8859-1"));

        // 读取文件的字节流
        os.write(FileUtil.readBytes(uploadFile));
        os.flush();
        os.close();
    }

    /**
     * 通过md5查询文件
     *
     * @param md5
     */
    public UserFile getFileByMd5(String md5) {
        QueryWrapper<UserFile> userFileQueryWrapper = new QueryWrapper<>();
        userFileQueryWrapper.eq("md5", md5);
        List<UserFile> list = fileService.list(userFileQueryWrapper);
        return list.size() == 0 ? null : list.get(0);
    }

}
